using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using AesonBaseFramework.EntityFramework.DbContexts;
using AesonIdentityLibrary.DataContext;
using AesonIdentityLibrary.DataModel;
using Microsoft.AspNet.Identity;

namespace AesonIdentityLibrary.Repositories
{

    public class UserStore : IQueryableUserStore<ApplicationUser, int>,
                               IUserPasswordStore<ApplicationUser,int>,
                                  IUserSecurityStampStore<ApplicationUser,int>,
                                    IUserStore<ApplicationUser,int>,
                                      IUserEmailStore<ApplicationUser,int>,
                                       IDisposable
    {

        #region Ctor
        private readonly SecurityDbContext _db;

        public UserStore(SecurityDbContext db)
        {
            this._db = db;
        }
      
        #endregion

        #region IUserStore

        public IQueryable<ApplicationUser> Users
        {
            get { return _db.Users; }
        }

        public async Task CreateAsync(ApplicationUser user)
        {
            this._db.Users.Add(user);
            await this._db.SaveChangesAsync();
        }

        public async Task UpdateAsync(ApplicationUser user)
        {
            this._db.Entry(user).State = EntityState.Modified;
            await this._db.SaveChangesAsync();
        }

        public async Task DeleteAsync(ApplicationUser user)
        {
            this._db.Entry(user).State = EntityState.Deleted;
            await this._db.SaveChangesAsync();
        }

        public async Task<ApplicationUser> FindByIdAsync(int userId)
        {
            return await this._db.Users.FirstOrDefaultAsync(u => u.Id == userId);
        }

        public async Task<ApplicationUser> FindByNameAsync(string userName)
        {
            return await this._db.Users.FirstOrDefaultAsync(u => u.UserName == userName);
        }

        #endregion

        #region IUserPasswordStore
        public async Task SetPasswordHashAsync(ApplicationUser user, string passwordHash)
        {
            user.PasswordHash = passwordHash;
        }

        public async Task<string> GetPasswordHashAsync(ApplicationUser user)
        {
            var dbUser = await this._db.Users.FirstOrDefaultAsync(u => u.Id == user.Id);
            if (dbUser != null)
            {
                return dbUser.PasswordHash;
            }

            return string.Empty;
        }

        public async Task<bool> HasPasswordAsync(ApplicationUser user)
        {
            var dbUser = await this._db.Users.FirstOrDefaultAsync(u => u.Id == user.Id);
            if (dbUser != null)
            {
                return !string.IsNullOrEmpty(dbUser.PasswordHash);
            }

            return false;
        }
        #endregion

        #region IUserSecurityStampStore
        public async Task SetSecurityStampAsync(ApplicationUser user, string stamp)
        {
            user.SecurityStamp = stamp;
        }

        public async Task<string> GetSecurityStampAsync(ApplicationUser user)
        {
            var dbUser = await this._db.Users.FirstOrDefaultAsync(u => u.Id == user.Id);
            if (dbUser != null)
            {
                return dbUser.SecurityStamp;
            }

            return string.Empty;
        }
        #endregion

        #region IUserEmailStore
        public Task<ApplicationUser> FindByEmailAsync(string email)
        {
            
            return this._db.Users.FirstOrDefaultAsync(u => u.EMail == email);
        }

        public Task<string> GetEmailAsync(ApplicationUser user)
        {
            return Task.FromResult(user.EMail);
        }

        public Task<bool> GetEmailConfirmedAsync(ApplicationUser user)
        {
            throw new NotImplementedException();
        }

        public Task SetEmailAsync(ApplicationUser user, string email)
        {
            throw new NotImplementedException();
        }

        public Task SetEmailConfirmedAsync(ApplicationUser user, bool confirmed)
        {
            throw new NotImplementedException();
        }
        #endregion

        public async Task<List<ApplicationUser>> ListAsync()
        {
            return await this._db.Users.OrderBy(u => u.UserName).ToListAsync();
        }

        public void Dispose()
        {
            this._db.Dispose();
        }



       


   
    }
}



